"""
资源规划应用程序 - 简化版本

支持单一Excel文件输入，自动生成日本模板格式的资源计划输出
"""

import logging
import sys
import os
from pathlib import Path
from datetime import datetime, date
from typing import Dict, List, Optional, Tuple
import yaml
import pandas as pd
from openpyxl import Workbook, load_workbook
from openpyxl.styles import PatternFill, Font, Alignment, Border, Side
from openpyxl.utils.dataframe import dataframe_to_rows
from dateutil.relativedelta import relativedelta

# 添加src目录到Python路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from models.simple_models import ProjectInfo, ProjectRole, PhaseDetail, MonthlyAllocation
from services.resource_calculator import ResourceCalculator
from template_filler import TemplateFiller


class ResourcePlanApp:
    """资源规划应用程序主类"""

    def __init__(self, config_path: str = "config.yaml", debug: bool = False):
        """
        初始化应用程序

        Args:
            config_path: 配置文件路径
            debug: 是否启用调试模式
        """
        self.config_path = config_path
        self.debug = debug
        self.config = {}
        self.logger = None

        # 业务数据
        self.project_info: Optional[ProjectInfo] = None
        self.project_roles: List[ProjectRole] = []
        self.phases_detail: List[PhaseDetail] = []
        self.monthly_allocations: List[MonthlyAllocation] = []

        # 业务对象
        self.calculator = ResourceCalculator()
        self.template_filler = None

        self._setup_application()

    def _setup_application(self):
        """初始化应用程序配置"""
        try:
            self._load_config()
            self._setup_logging()

            self.logger.info("资源规划应用程序初始化完成")

        except Exception as e:
            print(f"应用程序初始化失败：{e}")
            if self.debug:
                import traceback
                traceback.print_exc()
            sys.exit(1)

    def _load_config(self):
        """加载配置文件"""
        config_file = Path(self.config_path)
        if not config_file.exists():
            # 使用默认配置
            self.config = {
                "logging": {"level": "INFO"},
                "algorithm": {
                    "tl_calculation": {
                        "enabled": True,
                        "ratio": 3
                    }
                },
                "output": {
                    "directory": "data/output",
                    "filename_pattern": "resource_plan_{date}_v{version}.xlsx"
                }
            }
            print(f"使用默认配置（配置文件 {self.config_path} 不存在）")
            return

        try:
            with open(config_file, 'r', encoding='utf-8') as f:
                self.config = yaml.safe_load(f)
            print(f"配置文件加载成功：{self.config_path}")
        except Exception as e:
            raise Exception(f"配置文件解析失败：{e}")

    def _setup_logging(self):
        """设置日志配置"""
        log_config = self.config.get("logging", {})
        log_level = "DEBUG" if self.debug else log_config.get("level", "INFO")

        # 设置日志格式
        log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

        # 配置根日志器
        logging.basicConfig(
            level=getattr(logging, log_level.upper()),
            format=log_format,
            handlers=[logging.StreamHandler(sys.stdout)],
            force=True
        )

        self.logger = logging.getLogger(__name__)
        self.logger.info(f"日志系统初始化完成，级别：{log_level}")

    def load_input_data(self, input_file: str) -> bool:
        """
        加载输入数据文件

        Args:
            input_file: 输入Excel文件路径

        Returns:
            bool: 加载是否成功
        """
        try:
            self.logger.info(f"开始加载输入数据文件：{input_file}")

            # 检查文件是否存在
            if not Path(input_file).exists():
                raise FileNotFoundError(f"输入文件不存在：{input_file}")

            # 基本验证：检查Excel文件是否有必需的sheet
            try:
                excel_file = pd.ExcelFile(input_file)
                required_sheets = ['project_info', 'project_roles', 'phases_detail']
                missing_sheets = [sheet for sheet in required_sheets if sheet not in excel_file.sheet_names]

                if missing_sheets:
                    self.logger.error(f"Excel文件缺少必需的sheet：{missing_sheets}")
                    return False

                self.logger.info("Excel文件基本结构验证通过")
            except Exception as e:
                self.logger.error(f"Excel文件读取失败：{e}")
                return False

            # 读取Excel文件
            excel_file = pd.ExcelFile(input_file)

            # 读取项目信息
            if 'project_info' in excel_file.sheet_names:
                df_project = pd.read_excel(excel_file, 'project_info')
                if not df_project.empty:
                    row = df_project.iloc[0]
                    self.project_info = ProjectInfo(
                        project_id=str(row['project_id']),
                        project_name=str(row['project_name']),
                        start_date=pd.to_datetime(row['start_date']).date(),
                        end_date=pd.to_datetime(row['end_date']).date(),
                        budget=float(row['budget']),
                        description=str(row.get('description', ''))
                    )

            # 读取项目角色
            if 'project_roles' in excel_file.sheet_names:
                df_roles = pd.read_excel(excel_file, 'project_roles')
                self.project_roles = []
                for _, row in df_roles.iterrows():
                    role = ProjectRole(
                        project_id=str(row['project_id']),
                        role=str(row['role']),
                        unit_price=float(row['unit_price']),
                        total_cost=float(row.get('total_cost', 0))
                    )
                    self.project_roles.append(role)

            # 读取阶段详情
            if 'phases_detail' in excel_file.sheet_names:
                df_phases = pd.read_excel(excel_file, 'phases_detail')
                self.phases_detail = []
                for _, row in df_phases.iterrows():
                    phase = PhaseDetail(
                        project_id=str(row['project_id']),
                        phase_name=str(row['phase_name']),
                        start_date=pd.to_datetime(row['start_date']).date(),
                        end_date=pd.to_datetime(row['end_date']).date(),
                        role=str(row['role']),
                        unit_price=float(row['unit_price']),
                        person_months=float(row['person_months'])
                    )
                    self.phases_detail.append(phase)

            # 打印加载统计
            self.logger.info("数据加载完成：")
            self.logger.info(f"  - 项目信息：{'已加载' if self.project_info else '未找到'}")
            self.logger.info(f"  - 项目角色：{len(self.project_roles)} 个")
            self.logger.info(f"  - 阶段详情：{len(self.phases_detail)} 个")

            return True

        except Exception as e:
            self.logger.error(f"数据加载失败：{e}")
            if self.debug:
                import traceback
                traceback.print_exc()
            return False

    def calculate_resources(self) -> bool:
        """
        执行资源计算

        Returns:
            bool: 计算是否成功
        """
        try:
            self.logger.info("开始执行资源计算...")

            if not self.project_info or not self.phases_detail:
                raise ValueError("数据未完整加载，无法执行计算")

            # 配置TL计算选项
            tl_config = self.config.get("algorithm", {}).get("tl_calculation", {})
            tl_enabled = tl_config.get("enabled", True)
            tl_ratio = tl_config.get("ratio", 3)

            # 执行资源计算
            self.monthly_allocations = self.calculator.calculate_monthly_allocations(
                self.phases_detail,
                tl_enabled=tl_enabled,
                tl_ratio=tl_ratio
            )

            self.logger.info(f"资源计算完成，生成 {len(self.monthly_allocations)} 个月度分配记录")

            # 输出计算统计
            total_person_months = sum(alloc.person_count for alloc in self.monthly_allocations)
            total_cost = sum(alloc.cost for alloc in self.monthly_allocations)

            self.logger.info(f"总人月数：{total_person_months:.1f}")
            self.logger.info(f"总成本：{total_cost:,.0f}")

            return True

        except Exception as e:
            self.logger.error(f"资源计算失败：{e}")
            if self.debug:
                import traceback
                traceback.print_exc()
            return False

    def generate_output(self, output_dir: str = None, use_template: bool = True) -> bool:
        """
        生成输出文件

        Args:
            output_dir: 输出目录
            use_template: 是否使用模板文件

        Returns:
            bool: 生成是否成功
        """
        try:
            if not self.monthly_allocations:
                raise ValueError("未执行计算，无法生成输出")

            self.logger.info("开始生成输出文件...")

            # 确定输出目录
            output_config = self.config.get("output", {})
            output_dir = output_dir or output_config.get("directory", "data/output")
            output_path = Path(output_dir)
            output_path.mkdir(parents=True, exist_ok=True)

            # 生成文件名
            filename_pattern = output_config.get("filename_pattern", "resource_plan_{date}_v{version}.xlsx")
            output_filename = filename_pattern.format(
                date=datetime.now().strftime("%Y%m%d"),
                version="01"
            )

            output_file = output_path / output_filename

            # 生成Excel文件
            if use_template:
                # 使用模板生成
                self._generate_template_output(output_file)
            else:
                # 使用自定义格式生成
                self._generate_excel_output(output_file)

            # 生成文本报告
            self._generate_text_report(output_file.with_suffix('.txt'))

            self.logger.info(f"输出文件生成完成：{output_file}")
            return True

        except Exception as e:
            self.logger.error(f"输出生成失败：{e}")
            if self.debug:
                import traceback
                traceback.print_exc()
            return False

    def _generate_template_output(self, output_file: Path):
        """使用模板生成Excel输出"""
        template_path = "Template/【公開用】PM_要員計画（山積み表・リソースヒストグラム）_20211121_01.xlsx"

        if not Path(template_path).exists():
            self.logger.warning(f"模板文件不存在：{template_path}，使用自定义格式")
            self._generate_excel_output(output_file)
            return

        try:
            # 初始化模板填充器
            if not self.template_filler:
                self.template_filler = TemplateFiller(template_path)

            # 填充模板
            success = self.template_filler.fill_template_with_data(
                self.monthly_allocations,
                self.project_info,
                str(output_file)
            )

            if not success:
                self.logger.warning("模板填充失败，使用自定义格式")
                self._generate_excel_output(output_file)

        except Exception as e:
            self.logger.error(f"模板处理失败：{e}，使用自定义格式")
            self._generate_excel_output(output_file)

    def _generate_excel_output(self, output_file: Path):
        """生成Excel格式的输出"""
        wb = Workbook()

        # 删除默认工作表
        wb.remove(wb.active)

        # 创建山積み表
        self._create_resource_allocation_sheet(wb)

        # 创建リソースヒストグラム
        self._create_resource_histogram_sheet(wb)

        # 创建汇总表
        self._create_summary_sheet(wb)

        # 保存文件
        wb.save(output_file)
        self.logger.info(f"Excel文件已保存：{output_file}")

    def _create_resource_allocation_sheet(self, wb: Workbook):
        """创建资源分配表（山積み表）"""
        ws = wb.create_sheet("山積み表")

        # 设置标题
        ws['A1'] = "资源分配表（山積み表）"
        ws['A1'].font = Font(size=14, bold=True)

        # 创建数据框
        if self.monthly_allocations:
            # 获取所有月份
            all_months = sorted(set(alloc.month for alloc in self.monthly_allocations))
            all_roles = sorted(set(alloc.role for alloc in self.monthly_allocations))

            # 创建透视表数据
            data = []
            for role in all_roles:
                row = [role]
                for month in all_months:
                    count = sum(
                        alloc.person_count
                        for alloc in self.monthly_allocations
                        if alloc.role == role and alloc.month == month
                    )
                    row.append(count if count > 0 else "")
                data.append(row)

            # 写入表头
            header = ["角色"] + [month.strftime("%Y-%m") for month in all_months]
            for col, value in enumerate(header, 1):
                cell = ws.cell(row=3, column=col, value=value)
                cell.font = Font(bold=True)
                cell.fill = PatternFill(start_color="CCCCCC", end_color="CCCCCC", fill_type="solid")

            # 写入数据
            for row_idx, row_data in enumerate(data, 4):
                for col_idx, value in enumerate(row_data, 1):
                    ws.cell(row=row_idx, column=col_idx, value=value)

        # 调整列宽
        for column in ws.columns:
            max_length = 0
            column_letter = column[0].column_letter
            for cell in column:
                try:
                    if len(str(cell.value)) > max_length:
                        max_length = len(str(cell.value))
                except:
                    pass
            adjusted_width = min(max_length + 2, 20)
            ws.column_dimensions[column_letter].width = adjusted_width

    def _create_resource_histogram_sheet(self, wb: Workbook):
        """创建资源直方图表（リソースヒストグラム）"""
        ws = wb.create_sheet("リソースヒストグラム")

        # 设置标题
        ws['A1'] = "资源直方图（リソースヒストグラム）"
        ws['A1'].font = Font(size=14, bold=True)

        if self.monthly_allocations:
            # 按月份汇总总人数
            monthly_totals = {}
            for alloc in self.monthly_allocations:
                if alloc.month not in monthly_totals:
                    monthly_totals[alloc.month] = 0
                monthly_totals[alloc.month] += alloc.person_count

            # 写入表头
            ws['A3'] = "月份"
            ws['B3'] = "总人数"
            ws['C3'] = "总成本"

            for cell in [ws['A3'], ws['B3'], ws['C3']]:
                cell.font = Font(bold=True)
                cell.fill = PatternFill(start_color="CCCCCC", end_color="CCCCCC", fill_type="solid")

            # 写入数据
            sorted_months = sorted(monthly_totals.keys())
            for idx, month in enumerate(sorted_months, 4):
                ws.cell(row=idx, column=1, value=month.strftime("%Y-%m"))
                ws.cell(row=idx, column=2, value=monthly_totals[month])

                # 计算月度成本
                monthly_cost = sum(
                    alloc.cost
                    for alloc in self.monthly_allocations
                    if alloc.month == month
                )
                ws.cell(row=idx, column=3, value=monthly_cost)

        # 调整列宽
        ws.column_dimensions['A'].width = 12
        ws.column_dimensions['B'].width = 10
        ws.column_dimensions['C'].width = 15

    def _create_summary_sheet(self, wb: Workbook):
        """创建汇总表"""
        ws = wb.create_sheet("汇总表")

        # 设置标题
        ws['A1'] = "项目资源汇总"
        ws['A1'].font = Font(size=14, bold=True)

        row = 3

        # 项目基本信息
        if self.project_info:
            ws[f'A{row}'] = "项目信息"
            ws[f'A{row}'].font = Font(bold=True)
            row += 1

            ws[f'A{row}'] = "项目名称："
            ws[f'B{row}'] = self.project_info.project_name
            row += 1

            ws[f'A{row}'] = "项目周期："
            ws[f'B{row}'] = f"{self.project_info.start_date} ~ {self.project_info.end_date}"
            row += 1

            ws[f'A{row}'] = "项目预算："
            ws[f'B{row}'] = f"{self.project_info.budget:,.0f}"
            row += 2

        # 资源统计
        if self.monthly_allocations:
            ws[f'A{row}'] = "资源统计"
            ws[f'A{row}'].font = Font(bold=True)
            row += 1

            # 按角色统计
            role_stats = {}
            for alloc in self.monthly_allocations:
                if alloc.role not in role_stats:
                    role_stats[alloc.role] = {'person_months': 0, 'cost': 0}
                role_stats[alloc.role]['person_months'] += alloc.person_count
                role_stats[alloc.role]['cost'] += alloc.cost

            ws[f'A{row}'] = "角色"
            ws[f'B{row}'] = "总人月"
            ws[f'C{row}'] = "总成本"

            for cell in [ws[f'A{row}'], ws[f'B{row}'], ws[f'C{row}']]:
                cell.font = Font(bold=True)
                cell.fill = PatternFill(start_color="CCCCCC", end_color="CCCCCC", fill_type="solid")

            row += 1

            for role, stats in sorted(role_stats.items()):
                ws[f'A{row}'] = role
                ws[f'B{row}'] = f"{stats['person_months']:.1f}"
                ws[f'C{row}'] = f"{stats['cost']:,.0f}"
                row += 1

            row += 1

            # 总计
            total_person_months = sum(stats['person_months'] for stats in role_stats.values())
            total_cost = sum(stats['cost'] for stats in role_stats.values())

            ws[f'A{row}'] = "总计"
            ws[f'B{row}'] = f"{total_person_months:.1f}"
            ws[f'C{row}'] = f"{total_cost:,.0f}"

            for cell in [ws[f'A{row}'], ws[f'B{row}'], ws[f'C{row}']]:
                cell.font = Font(bold=True)
                cell.fill = PatternFill(start_color="FFFF99", end_color="FFFF99", fill_type="solid")

        # 调整列宽
        ws.column_dimensions['A'].width = 15
        ws.column_dimensions['B'].width = 12
        ws.column_dimensions['C'].width = 15

    def _generate_text_report(self, output_file: Path):
        """生成文本格式的报告"""
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write("资源规划计算结果报告\n")
            f.write("=" * 50 + "\n\n")

            # 项目基本信息
            if self.project_info:
                f.write("项目信息：\n")
                f.write(f"  项目名称：{self.project_info.project_name}\n")
                f.write(f"  项目周期：{self.project_info.start_date} ~ {self.project_info.end_date}\n")
                f.write(f"  项目预算：{self.project_info.budget:,.0f}\n\n")

            # 月度分配详情
            if self.monthly_allocations:
                f.write("月度资源分配：\n")
                current_month = None
                for alloc in sorted(self.monthly_allocations, key=lambda x: (x.month, x.role)):
                    if alloc.month != current_month:
                        current_month = alloc.month
                        f.write(f"\n{current_month.strftime('%Y年%m月')}：\n")

                    f.write(f"  {alloc.role}: {alloc.person_count:.1f}人 "
                           f"({alloc.phase_name}) - 成本：{alloc.cost:,.0f}\n")

                f.write("\n")

                # 统计汇总
                f.write("统计汇总：\n")
                role_stats = {}
                for alloc in self.monthly_allocations:
                    if alloc.role not in role_stats:
                        role_stats[alloc.role] = {'person_months': 0, 'cost': 0}
                    role_stats[alloc.role]['person_months'] += alloc.person_count
                    role_stats[alloc.role]['cost'] += alloc.cost

                for role, stats in sorted(role_stats.items()):
                    f.write(f"  {role}: {stats['person_months']:.1f}人月，"
                           f"成本：{stats['cost']:,.0f}\n")

                total_person_months = sum(stats['person_months'] for stats in role_stats.values())
                total_cost = sum(stats['cost'] for stats in role_stats.values())

                f.write(f"\n总计：{total_person_months:.1f}人月，总成本：{total_cost:,.0f}\n")

    def run_complete_workflow(self, input_file: str, output_dir: str = None, verbose: bool = False) -> bool:
        """
        执行完整的工作流程

        Args:
            input_file: 输入Excel文件路径
            output_dir: 输出目录
            verbose: 是否详细输出

        Returns:
            bool: 整个流程是否成功
        """
        self.logger.info("开始执行完整的资源规划工作流程")

        try:
            # 1. 数据加载
            if not self.load_input_data(input_file):
                return False

            # 2. 资源计算
            if not self.calculate_resources():
                return False

            # 3. 生成输出
            if not self.generate_output(output_dir):
                return False

            # 4. 显示详细信息
            if verbose:
                self._display_detailed_results()

            self.logger.info("完整工作流程执行成功！")
            return True

        except Exception as e:
            self.logger.error(f"工作流程执行失败：{e}")
            if self.debug:
                import traceback
                traceback.print_exc()
            return False

    def _display_detailed_results(self):
        """在控制台显示详细结果"""
        print("\n" + "=" * 60)
        print("详细计算结果")
        print("=" * 60)

        if self.project_info:
            print(f"\n【项目信息】")
            print(f"  项目名称：{self.project_info.project_name}")
            print(f"  项目周期：{self.project_info.start_date} ~ {self.project_info.end_date}")
            print(f"  项目预算：{self.project_info.budget:,.0f}")

        if self.monthly_allocations:
            print(f"\n【月度资源分配】")
            current_month = None
            for alloc in sorted(self.monthly_allocations, key=lambda x: (x.month, x.role)):
                if alloc.month != current_month:
                    current_month = alloc.month
                    print(f"\n  {current_month.strftime('%Y年%m月')}：")

                print(f"    {alloc.role:8} {alloc.person_count:5.1f}人 "
                     f"({alloc.phase_name:12}) - {alloc.cost:8,.0f}元")

            # 按角色统计
            print(f"\n【角色统计】")
            role_stats = {}
            for alloc in self.monthly_allocations:
                if alloc.role not in role_stats:
                    role_stats[alloc.role] = {'person_months': 0, 'cost': 0}
                role_stats[alloc.role]['person_months'] += alloc.person_count
                role_stats[alloc.role]['cost'] += alloc.cost

            for role, stats in sorted(role_stats.items()):
                print(f"  {role:8} {stats['person_months']:6.1f}人月  {stats['cost']:10,.0f}元")

            total_person_months = sum(stats['person_months'] for stats in role_stats.values())
            total_cost = sum(stats['cost'] for stats in role_stats.values())

            print(f"\n  {'总计':8} {total_person_months:6.1f}人月  {total_cost:10,.0f}元")

        print("\n" + "=" * 60)

    def get_summary(self) -> Dict:
        """
        获取应用程序运行摘要

        Returns:
            Dict: 摘要信息
        """
        summary = {
            "config_loaded": bool(self.config),
            "data_loaded": bool(self.project_info and self.phases_detail),
            "calculation_completed": bool(self.monthly_allocations),
            "data_counts": {
                "project_roles": len(self.project_roles),
                "phases_detail": len(self.phases_detail),
                "monthly_allocations": len(self.monthly_allocations)
            }
        }

        if self.monthly_allocations:
            total_person_months = sum(alloc.person_count for alloc in self.monthly_allocations)
            total_cost = sum(alloc.cost for alloc in self.monthly_allocations)

            summary["calculation_results"] = {
                "total_person_months": total_person_months,
                "total_cost": total_cost,
                "unique_roles": len(set(alloc.role for alloc in self.monthly_allocations)),
                "duration_months": len(set(alloc.month for alloc in self.monthly_allocations))
            }

        return summary